﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace EmperialApps.WeatherSpark.Data {

    /// <summary>Represents an ephemeral local message log.</summary>
    public static class Logger {

        private static readonly DateTimeOffset _start = DateTimeOffset.Now;
        private static readonly string[] _log = new string[Capacity];
        private static int _count;

        /// <summary>Gets the maximum number of messages that can be logged before earlier messages are overwritten.</summary>
        public const int Capacity = 250;

        /// <summary>Gets the total number of messages that have been written to the log.</summary>
        public static int Count { get { return _count; } }

        /// <summary>Gets or sets a prefix used to distinguish application and agent logs.</summary>
        public static string DebugPrefix { get; set; }

        /// <summary>Logs a message.</summary>
        public static void Log( this Type type, string message ) {
            if( string.IsNullOrEmpty( message ) )
                return;

            int index = (Interlocked.Increment( ref _count ) - 1) % Capacity;

            TimeSpan offset = DateTimeOffset.Now - _start;
#if DEBUG
            string typeName = string.Format( "[{0:x}] {1}", Thread.CurrentThread.ManagedThreadId, type.Name );
#else
            string typeName = type.Name;
#endif
            _log[index] = string.Format( "[{0:000.000}] {1:000} {2}: {3}", offset.TotalSeconds, Count, typeName, message );
            System.Diagnostics.Debug.WriteLine( DebugPrefix + "LOG: " + _log[index] );
        }

        /// <summary>Gets the current set of logged messages (within capacity).</summary>
        public static IEnumerable<string> GetLog( ) {
            int circularOffset = Count % Capacity;
            int circularCount = Math.Min( Count, Capacity ) - circularOffset;
            var log = _log.Skip( circularOffset ).Take( circularCount ).Concat( _log.Take( circularOffset ) );
            return log;
        }

        /// <summary>Clears all recorded messages from the log.</summary>
        public static void ClearLog( ) {
            Interlocked.Exchange( ref _count, 0 );
        }

    }

}
